<template>
  <div class="content-item chart">
    <!-- 第一张：奖励变化曲线 -->
    <div class="chart-item">
      <div class="chart-item-header">奖励变化曲线</div>
      <div ref="RewardElRef" class="chart-card" />
      <p class="chart-item-describe" :title="RewardDescription">
        {{ RewardDescription }}
      </p>
    </div>

    <!-- 第二张：胜率变化曲线 -->
    <div class="chart-item">
      <div class="chart-item-header">胜率变化曲线</div>
      <div ref="WinRateElRef" class="chart-card" />
      <p class="chart-item-describe" :title="WinRateDescription">
        {{ WinRateDescription }}
      </p>
    </div>

    <!-- 第三张：XXX 变化曲线（宽度同上） -->
    <div class="chart-item">
      <div class="chart-item-header">损失值变化曲线</div>
      <div ref="ThirdElRef" class="chart-card" />
      <p class="chart-item-describe" :title="ThirdDescription">
        {{ ThirdDescription }}
      </p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, onActivated, watch, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import type { SeriesOption } from 'echarts'
import { getTaskProcessDataApi } from '@/common/apis/train'
import type { TrainProcessEvaData } from '@/common/apis/train/type'
import { useECharts } from '@/common/composables/useECharts'
import { MultipleLineOptionStrategy } from '@/common/components/Charts'

interface Props {
  taskStatus: number | undefined
  remainingWorkerNum: number
  usedWorkerNum: number
  maxRound: number
}
const props = defineProps<Props>()
const emit = defineEmits(['update:remainingWorkerNum', 'update:usedWorkerNum'])
const route = useRoute()

let timer: number | null = null
const taskId = ref(route.query.id as string)
const taskStatus = ref<number | undefined>(props.taskStatus)

const RewardElRef = ref<HTMLElement | null>(null)
const WinRateElRef = ref<HTMLElement | null>(null)
const ThirdElRef = ref<HTMLElement | null>(null)

const state = reactive<{
  round: number[]
  agents: Record<string, { reward: number[]; winRate: number[] }>
}>({
  round: Array.from({ length: props.maxRound }, (_, i) => i + 1),
  agents: {}
})

const RewardDescription = '反映智能体完成期望任务的水平。奖励对智能体做出引导，合适的算法设计能够让智能体获得较高的奖励。一般在训练后期，奖励会趋于稳定。'
const WinRateDescription = '反映智能体获取局数比例，一般胜率曲线与奖励曲线走势相仿。'
const ThirdDescription = '损失值反应对抗演练。'

const RewardChart = useECharts(
  RewardElRef,
  new MultipleLineOptionStrategy().getOptions({
    tooltip: { trigger: 'axis' },
    legend: { data: [] },
    xAxis: {
      type: 'category',
      name: '局数',
      data: state.round,
      axisLabel: { interval: 0, rotate: 45, margin: 15 },
      axisTick: { alignWithLabel: true }
    },
    yAxis: { type: 'value', name: '奖励值', nameLocation: 'middle', nameGap: 40 },
    series: []
  })
)

const WinRateChart = useECharts(
  WinRateElRef,
  new MultipleLineOptionStrategy().getOptions({
    tooltip: { trigger: 'axis' },
    legend: { data: [] },
    xAxis: { type: 'category', name: '局数', data: state.round, axisLabel: { interval: 0, rotate: 45 } },
    yAxis: { type: 'value', name: '胜率' },
    series: []
  })
)

const ThirdChart = useECharts(
  ThirdElRef,
  new MultipleLineOptionStrategy().getOptions({
    tooltip: { trigger: 'axis' },
    legend: { data: [] },
    xAxis: {
      type: 'category',
      name: '局数',
      data: state.round,
      axisLabel: { interval: 0, rotate: 45, margin: 15 },
      axisTick: { alignWithLabel: true }
    },
    yAxis: { type: 'value', name: '损失值', nameLocation: 'middle', nameGap: 40 },
    series: []
  })
)

function getTaskProcessData() {
  state.agents = {}
  getTaskProcessDataApi(taskId.value)
    .then(({ data }) => {
      data.forEach(item => {
        const processEval: TrainProcessEvaData = JSON.parse(item.process_eval)
        Object.entries(processEval).forEach(([agentName, agentData]) => {
          if (!state.agents[agentName]) {
            state.agents[agentName] = { reward: [], winRate: [] }
          }
          const d = agentData as { reward: number; win_rate: number }
          state.agents[agentName].reward.push(d.reward)
          state.agents[agentName].winRate.push(d.win_rate)
        })
        emit('update:usedWorkerNum', item.worker_res_info.used_worker_num)
        emit('update:remainingWorkerNum', item.worker_res_info.remaining_worker_num)
      })
    })
    .finally(() => {
      const rewardSeries = Object.entries(state.agents).map(([name, d]) => ({
        name: `${name} Reward`, type: 'line', smooth: true, data: d.reward
      }))
      const winRateSeries = Object.entries(state.agents).map(([name, d]) => ({
        name: `${name} Win Rate`, type: 'line', smooth: true, data: d.winRate
      }))
      const thirdSeries = rewardSeries // 替换为第三条真实数据

      // 更新第一、二张图
      RewardChart.options.legend && (RewardChart.options.legend.data = rewardSeries.map(s => s.name))
      RewardChart.options.series = rewardSeries as SeriesOption[]

      WinRateChart.options.legend && (WinRateChart.options.legend.data = winRateSeries.map(s => s.name))
      WinRateChart.options.series = winRateSeries as SeriesOption[]

      // 更新第三张图（确保 xAxis.data 也被更新）
      ThirdChart.options.xAxis && (ThirdChart.options.xAxis.data = state.round)
      ThirdChart.options.legend && (ThirdChart.options.legend.data = thirdSeries.map(s => s.name))
      ThirdChart.options.series = thirdSeries as SeriesOption[]
    })
}

function resize() {
  nextTick(() => {
    RewardChart.handleResize()
    WinRateChart.handleResize()
    ThirdChart.handleResize()
  })
}

watch(() => props.taskStatus, v => {
  taskStatus.value = v
  if (v === 1) getTaskProcessData()
})
watch(() => props.maxRound, v => {
  state.round = Array.from({ length: v }, (_, i) => i + 1)
  RewardChart.options.xAxis && (RewardChart.options.xAxis.data = state.round)
  WinRateChart.options.xAxis && (WinRateChart.options.xAxis.data = state.round)
  ThirdChart.options.xAxis && (ThirdChart.options.xAxis.data = state.round)
})

function refresh() { if (taskStatus.value === 1) getTaskProcessData() }
function restart() { getTaskProcessData() }

onMounted(() => {
  getTaskProcessData()
  timer = window.setInterval(refresh, 60 * 1000)
})
onBeforeUnmount(() => timer && clearInterval(timer))
onActivated(() => {
  if (route.query.id !== taskId.value) {
    taskId.value = route.query.id as string
    getTaskProcessData()
  }
})

defineExpose({ resize, restart })
</script>

<style lang="scss" scoped>
@import "@@/assets/styles/mixins.scss";

.content-item.chart {
  display: flex;
  flex-wrap: wrap;
  gap: var(--main-padding);
}

.chart-item {
  width: calc(50% - var(--main-padding) / 2);
  background: var(--el-bg-color);
  border-radius: 4px;
  padding: var(--main-padding);
  display: flex;
  flex-direction: column;
  min-height: 500px;
  height: calc(100vh / 2 - 200px);

  &-header {
    font-size: 16px;
    font-weight: 500;
    margin-bottom: 8px;
  }

  &-describe {
    width: 100%;
    height: 1.5em;
    line-height: 1.5em;
    padding-left: 30px;
    @extend %ellipsis;
  }

  .chart-card {
    flex: 1;
  }
}

@media screen and (max-width: 1400px) {
  .chart-item {
    width: 100% !important;
  }
}
</style>
